
import { _decorator, Component, Node, ScrollView, instantiate, UITransform, Layout, v3, Vec3, Size, NodePool, size, Rect, Vec2, Label, Prefab, Widget, CCBoolean } from 'cc';
import { DEBUG, DEV } from 'cc/env';
import { SuperContainer } from './SuperContainer';
import { ScrollItemView } from './ScrollItemView';
import { SuperButton } from '../base/SuperButton';
const { ccclass, property, requireComponent } = _decorator;




const _tempVec2 = new Vec2();
const _tempVec3 = new Vec3();
const _tempVec3_1 = new Vec3();
const _tempRect = new Rect();

/**
 * 优化的列表组件，动态加载显示的项
 */
@ccclass('ScrollViewHelper')
@requireComponent(ScrollView)
export class ScrollViewHelper extends SuperContainer {
    @property({ tooltip: DEV && "是否默认选择第一项" })
    @property(CCBoolean)
    defaultSelectedFirst: boolean = true;

    defaultSelectedItemView: SuperButton = null;

    @property({ tooltip: DEV && "是否启用自动布局，使用自动布局会失去优化功能但会支持不同尺寸item" })
    @property(CCBoolean)
    autoLayoutEnabled: boolean = false;

    private _scrollView: ScrollView = null;
    private _itemPool: NodePool = new NodePool();
    private _itemTemplate: Node | Prefab = null;
    private _contentLayout: Layout = null;
    private _itemContentSize: Size = new Size();
    private _itemAnchorPoint: Vec2 = new Vec2();
    private _viewRect: Rect = new Rect();
    private _startPosition: Vec3 = new Vec3();
    private _gridCol: number = 0;//列
    private _gridRow: number = 0;//行

    private _horizontalMoveable: boolean = true;
    private _verticalMoveable: boolean = true;

    private _datas: Array<any> = null;
    public get datas() {
        return this._datas;
    }



    public get scrollView() {
        return this._scrollView;
    }

    //cgw20221114 -----start 
    public set datas(data: Array<any>) {
        this._datas = data;
    }


    get content() {
        return this._scrollView.content;
    }

    getItemWidth() {
        return this._itemContentSize.x;
    }
    getItemHeight() {
        return this._itemContentSize.y;
    }

    pauseSystemEvents(flag: boolean) {
        this.scrollView.node.pauseSystemEvents(flag)
    }

    resumeSystemEvents(flag: boolean) {
        this.scrollView.node.resumeSystemEvents(flag)
    }

    getPercentByPos(pos: any, dir: number = 1): number {
        let content = this.content;
        let viewSize = 0;
        let contentSize = 0;
        let p = 0;
        if (this.scrollView.vertical) {
            contentSize = content.getComponent(UITransform).height;
            viewSize = this.scrollView.node.getComponent(UITransform).height;
            p = pos.y;

        } else {
            contentSize = content.getComponent(UITransform).width;
            viewSize = this.scrollView.node.getComponent(UITransform).width;
            p = pos.x;
        }

        if (contentSize < viewSize) {
            return 0
        }
        let total = contentSize - viewSize;
        let dis = dir * p - viewSize / 2;
        if (dis < 0) {
            dis = 0
        }
        let n = Math.floor(dis / total * 100) / 100;
        return n;
    }

    get percent() {
        return this.getPercentByPos(this.content.getPosition(), -1)
    }
    //----------------end 

    onLoad() {
        // super.onLoad();
        this._scrollView = this._scrollView || this.getComponent(ScrollView);

        if (!this.autoLayoutEnabled) {
            this._scrollView.node.on('scrolling', this.onScrolling, this);
        }

    }

    start() {
        let children = this._scrollView.content.children;
        for (let i = 0; i < children.length; i++) {
            this.listener?.onItemAdd(children[i].getComponent(SuperButton));
        }
    }

    public getItemViews(): SuperButton[] {
        let itemViews: SuperButton[] = [];
        let children = this._scrollView.content.children;
        for (let i = 0; i < children.length; i++) {
            itemViews.push(children[i].getComponent(SuperButton));
        }
        return itemViews;
    }

    // update (deltaTime: number) {
    // }

    /**
     * 初始化列表
     * @param itemTemplate 支持Node和Prefab
     * @param datas 
     */
    initView(itemTemplate: Node | Prefab, datas: Array<any>) {
        this.removeAllItems();
        this._datas = datas;
        this._itemTemplate = itemTemplate;
        let itemNode: Node = null;
        if (itemTemplate instanceof Node) {
            itemNode = (this._itemTemplate as Node);
            itemNode.active = false;
        } else {
            itemNode = instantiate(itemTemplate);
        }
        if (DEBUG && !itemNode.getComponent(ScrollItemView)) {
            console.error("itemNode需要ScrollItemView子类组件");
            return;
        }
        this._itemContentSize.set(itemNode.getComponent(UITransform).contentSize.width * Math.abs(itemNode.scale.x), itemNode.getComponent(UITransform).contentSize.height * itemNode.scale.y);
        this._itemAnchorPoint.set(itemNode.getComponent(UITransform).anchorPoint);
        this._scrollView = this._scrollView || this.getComponent(ScrollView);
        let viewUITransform = this._scrollView.node.getChildByName("view").getComponent(UITransform);
        this._viewRect.set(-viewUITransform.anchorPoint.x * viewUITransform.contentSize.width, -viewUITransform.anchorPoint.y * viewUITransform.contentSize.height, viewUITransform.contentSize.width, viewUITransform.contentSize.height);
        //扩大显示范围，前后多显示一个
        // if (this._scrollView.vertical) {
        //     this._viewRect.y -= this._itemContentSize.height;
        //     this._viewRect.height += this._itemContentSize.height;
        // } else if (this._scrollView.horizontal) {
        // }
        this._scrollView.content.getComponent(Widget)?.updateAlignment();
        this._contentLayout = this._scrollView.content.getComponent(Layout);
        let scrollUITransform = this._scrollView.content.getComponent(UITransform);
        let contentSize = scrollUITransform.contentSize;
        let contentAnchorPoint = scrollUITransform.anchorPoint;
        if (this.autoLayoutEnabled) {
            this._isHoverInited = false;
            this._isSelectedInited = false;
            this.initItems();
            if (this.isKeyboardActive) {
                this.selectedDefaultItem();
            }
            return;
        }

        this._contentLayout.enabled = false;
        if (this._contentLayout.type == Layout.Type.GRID) {
            if (this._scrollView.vertical) {
                if (this._contentLayout.startAxis == Layout.AxisDirection.VERTICAL) {
                    console.error("scrollView方向VERTICAL，需要content startAxis方向HORIZONTAL");
                }
                this._gridCol = Math.floor((contentSize.width - (this._contentLayout.paddingLeft + this._contentLayout.paddingRight) + this._contentLayout.spacingX) / (this._itemContentSize.width + this._contentLayout.spacingX));
                this._gridCol = Math.max(1, this._gridCol);
                this._gridRow = Math.ceil(datas.length / this._gridCol);
                contentSize.set(contentSize.width, (this._contentLayout.paddingTop + this._contentLayout.paddingBottom) + this._itemContentSize.height * this._gridRow + this._contentLayout.spacingY * Math.max(0, this._gridRow - 1));
            } else if (this._scrollView.horizontal) {
                if (this._contentLayout.startAxis == Layout.AxisDirection.HORIZONTAL) {
                    console.error("scrollView方向HORIZONTAL，需要content startAxis方向VERTICAL");
                }
                this._gridCol = Math.floor((contentSize.height - (this._contentLayout.paddingTop + this._contentLayout.paddingBottom) + this._contentLayout.spacingY) / (this._itemContentSize.height + this._contentLayout.spacingY));
                this._gridCol = Math.max(1, this._gridCol);
                this._gridRow = Math.ceil(datas.length / this._gridCol);
                contentSize.set((this._contentLayout.paddingLeft + this._contentLayout.paddingRight) + this._itemContentSize.width * this._gridRow + this._contentLayout.spacingX * Math.max(0, this._gridRow - 1), contentSize.height);
            }
            if (this._contentLayout.verticalDirection == Layout.VerticalDirection.TOP_TO_BOTTOM) {
                this._startPosition.y = contentSize.height * (1 - contentAnchorPoint.y) - this._contentLayout.paddingTop - this._itemContentSize.height * (1 - this._itemAnchorPoint.y);
            } else if (this._contentLayout.verticalDirection == Layout.VerticalDirection.BOTTOM_TO_TOP) {
                this._startPosition.y = contentSize.height * -contentAnchorPoint.y + this._contentLayout.paddingBottom + this._itemContentSize.height * this._itemAnchorPoint.y;
            }
            if (this._contentLayout.horizontalDirection == Layout.HorizontalDirection.LEFT_TO_RIGHT) {
                this._startPosition.x = contentSize.width * -contentAnchorPoint.x + this._contentLayout.paddingLeft + this._itemContentSize.width * this._itemAnchorPoint.x;
            } else if (this._contentLayout.horizontalDirection == Layout.HorizontalDirection.RIGHT_TO_LEFT) {
                this._startPosition.x = contentSize.width * (1 - contentAnchorPoint.x) - this._contentLayout.paddingRight - this._itemContentSize.width * (1 - this._itemAnchorPoint.x);
            }
            this._scrollView.content.getComponent(UITransform).contentSize = contentSize;
            this._horizontalMoveable = true;
            this._verticalMoveable = true;
        } else {
            this._gridRow = datas.length;
            if (this._scrollView.vertical) {
                if (this._contentLayout.type == Layout.Type.HORIZONTAL) {
                    console.error("scrollView方向VERTICAL，需要content方向VERTICAL");
                }
                contentSize.set(contentSize.width, (this._contentLayout.paddingTop + this._contentLayout.paddingBottom) + this._itemContentSize.height * datas.length + this._contentLayout.spacingY * Math.max(0, datas.length - 1));
                this._startPosition.x = 0;
                if (this._contentLayout.verticalDirection == Layout.VerticalDirection.TOP_TO_BOTTOM) {
                    this._startPosition.y = contentSize.height * (1 - contentAnchorPoint.y) - this._contentLayout.paddingTop - this._itemContentSize.height * (1 - this._itemAnchorPoint.y);
                } else if (this._contentLayout.verticalDirection == Layout.VerticalDirection.BOTTOM_TO_TOP) {
                    this._startPosition.y = contentSize.height * -contentAnchorPoint.y + this._contentLayout.paddingBottom + this._itemContentSize.height * this._itemAnchorPoint.y;
                }
                this._horizontalMoveable = false;
                this._verticalMoveable = true;
            } else if (this._scrollView.horizontal) {
                if (this._contentLayout.type == Layout.Type.VERTICAL) {
                    console.error("scrollView方向HORIZONTAL，需要content方向HORIZONTAL");
                }
                contentSize.set((this._contentLayout.paddingLeft + this._contentLayout.paddingRight) + this._itemContentSize.width * datas.length + this._contentLayout.spacingX * Math.max(0, datas.length - 1), contentSize.height);
                this._startPosition.y = 0;
                if (this._contentLayout.horizontalDirection == Layout.HorizontalDirection.LEFT_TO_RIGHT) {
                    this._startPosition.x = contentSize.width * -contentAnchorPoint.x + this._contentLayout.paddingLeft + this._itemContentSize.width * this._itemAnchorPoint.x;
                } else if (this._contentLayout.horizontalDirection == Layout.HorizontalDirection.RIGHT_TO_LEFT) {
                    this._startPosition.x = contentSize.width * (1 - contentAnchorPoint.x) - this._contentLayout.paddingRight - this._itemContentSize.width * (1 - this._itemAnchorPoint.x);
                }
                this._horizontalMoveable = true;
                this._verticalMoveable = false;
            }
            this._scrollView.content.getComponent(UITransform).contentSize = contentSize;
        }
        this._isHoverInited = false;
        this._isSelectedInited = false;
        this._updateRenderItems();
        if (this.defaultSelectedFirst) {
            this.defaultSelectedItemView = this.getItemWithIndex(0)?.getComponent(SuperButton);
        }
        if (this.isKeyboardActive) {
            this.selectedDefaultItem();
        }
    }

    /**
     * 刷新列表（用于当列表数量变化时）
     * @param removeChildren 是否移除子项，false仅刷新model
     */
    public updateView(removeChildren: boolean = true) {
        this.unselectedItemView();
        if (removeChildren) {
            let children = this._scrollView.content.children;
            while (children.length > 0) {
                const itemNode = children[0];
                this._itemPool.put(itemNode);
                itemNode.getComponent(ScrollItemView).unuseFunc();
            }
        } else {
            let children = this._scrollView.content.children;
            for (let i = 0; i < children.length; i++) {
                let itemView = children[i].getComponent(ScrollItemView);
                itemView.useFunc(this._datas[itemView.index], itemView.index);
            }
        }
        this._isHoverInited = false;
        this._isSelectedInited = false;
        this._updateRenderItems();
    }

    private _isInView(position: Vec3) {
        this._scrollView.content.getComponent(UITransform).convertToWorldSpaceAR(position, _tempVec3_1);
        // Debug.log("1", _tempVec3_1);
        this._scrollView.content.parent.getComponent(UITransform).convertToNodeSpaceAR(_tempVec3_1, _tempVec3_1);
        // Debug.log("2", _tempVec3_1);
        _tempRect.set(_tempVec3_1.x - this._itemAnchorPoint.x * this._itemContentSize.width, _tempVec3_1.y - this._itemAnchorPoint.y * this._itemContentSize.height, this._itemContentSize.width, this._itemContentSize.height);
        // Debug.log(this._viewRect, _tempRect);
        return this._viewRect.intersects(_tempRect);
    }

    private _useItem(index: number, position?: Vec3) {
        let itemNode = this.getItemWithIndex(index);
        if (itemNode) {
            return;
        }
        // console.log("useItem" + index);
        itemNode = this._itemPool.get();
        if (!itemNode) {
            itemNode = instantiate(this._itemTemplate) as Node;
            itemNode.active = true;
            let superButton = itemNode.getComponent(SuperButton) || itemNode.addComponent(SuperButton);
            superButton.check.isChecked = false;
            superButton.sHoverCallback = this.onItemHoverCallback.bind(this);
            superButton.sSelectedCallback = this.onItemSelectedCallback.bind(this);
            this.listener?.onItemAdd(superButton);
        }
        // itemNode["__index"] = index;
        // itemNode["__data"] = this._datas[index];
        if (position) {
            itemNode.position = position;
        }
        this._scrollView.content.addChild(itemNode);

        // //TODO test
        // itemNode.getChildByName("testName")?.destroy();
        // let node = new Node("testName");
        // node.layer = itemNode.layer;
        // let label = node.addComponent(Label);
        // label.string = "" + itemNode["__index"];
        // node.position = v3(0, 0, 0);
        // itemNode.addChild(node);

        // this._scrollView.scheduleOnce(() => {//延迟一帧排序，解决排序错乱问题
        //     this._scrollView.content.children.sort((a, b) => a.getComponent(ScrollItemView).index - b.getComponent(ScrollItemView).index);
        // }, 0);
        itemNode.getComponent(ScrollItemView).useFunc(this._datas[index], index);
    }

    private _unuseItem(index: number) {
        let itemNode = this.getItemWithIndex(index);
        if (!itemNode) {
            return;
        }
        let superButton = itemNode.getComponent(SuperButton);
        if (superButton && (superButton.check.isChecked || superButton.isFocused())) {
            return;
        }
        // console.log("unuseItem" + index);
        this._itemPool.put(itemNode);
        // this._scrollView.content.children.sort((a, b) => a.getComponent(ScrollItemView).index - b.getComponent(ScrollItemView).index)
        itemNode.getComponent(ScrollItemView).unuseFunc();
    }

    private _getPositionWithIndex(index: number, out?: Vec3): Vec3 {
        out = out || new Vec3();
        if (this._contentLayout.type == Layout.Type.GRID) {
            out.set(0, 0, 0);
            let x = 0, y = 0;
            if (this._scrollView.vertical) {
                x = index % this._gridCol;
                y = Math.floor(index / this._gridCol);
            } else if (this._scrollView.horizontal) {
                x = Math.floor(index / this._gridCol);
                y = index % this._gridCol;
            }
            if (this._contentLayout.horizontalDirection == Layout.HorizontalDirection.LEFT_TO_RIGHT) {
                out.set(this._startPosition.x + x * (this._itemContentSize.width + this._contentLayout.spacingX)), out.y;
            } else if (this._contentLayout.horizontalDirection == Layout.HorizontalDirection.RIGHT_TO_LEFT) {
                out.set(this._startPosition.x - x * (this._itemContentSize.width + this._contentLayout.spacingX)), out.y;
            }
            if (this._contentLayout.verticalDirection == Layout.VerticalDirection.TOP_TO_BOTTOM) {
                out.set(out.x, this._startPosition.y - y * (this._itemContentSize.height + this._contentLayout.spacingY));
            } else if (this._contentLayout.verticalDirection == Layout.VerticalDirection.BOTTOM_TO_TOP) {
                out.set(out.x, this._startPosition.y + y * (this._itemContentSize.height + this._contentLayout.spacingY));
            }
        } else {
            out.set(0, 0, 0);
            if (this._scrollView.vertical) {
                if (this._contentLayout.verticalDirection == Layout.VerticalDirection.TOP_TO_BOTTOM) {
                    out.set(0, this._startPosition.y - index * (this._itemContentSize.height + this._contentLayout.spacingY));
                } else if (this._contentLayout.verticalDirection == Layout.VerticalDirection.BOTTOM_TO_TOP) {
                    out.set(0, this._startPosition.y + index * (this._itemContentSize.height + this._contentLayout.spacingY));
                }
            } else if (this._scrollView.horizontal) {
                if (this._contentLayout.horizontalDirection == Layout.HorizontalDirection.LEFT_TO_RIGHT) {
                    out.set(this._startPosition.x + index * (this._itemContentSize.width + this._contentLayout.spacingX)), 0;
                } else if (this._contentLayout.horizontalDirection == Layout.HorizontalDirection.RIGHT_TO_LEFT) {
                    out.set(this._startPosition.x - index * (this._itemContentSize.width + this._contentLayout.spacingX)), 0;
                }
            }
        }

        return out;
    }

    private _updateRenderItems(ignoreUnuse: boolean = false) {
        if (this.autoLayoutEnabled) {
            return;
        }
        if (!this._datas) {
            console.error("列表未初始化", this.node.name);
            return;
        }
        if (this._contentLayout.type == Layout.Type.GRID) {
            for (let i = 0; i < this._datas.length; ++i) {
                this._getPositionWithIndex(i, _tempVec3);
                if (this._isInView(_tempVec3)) {
                    this._useItem(i, _tempVec3);
                } else {
                    if (!ignoreUnuse) this._unuseItem(i);
                }
            }
        } else {
            for (let i = 0; i < this._datas.length; ++i) {
                this._getPositionWithIndex(i, _tempVec3);
                // Debug.log("1111111111a ", i, _tempVec3);
                if (this._isInView(_tempVec3)) {
                    this._useItem(i, _tempVec3);
                    // Debug.log("1111111111a in");
                } else {
                    if (!ignoreUnuse) this._unuseItem(i);
                    // Debug.log("1111111111a out");
                }
            }
        }
    }

    // public forceUpdateRenderItems() {
    //     this._updateRenderItems();
    // }

    /**
     * 获取指定item
     * @param index item在datas里的索引 
     * @param force 是否强制获取
     * @returns 
     */
    public getItemWithIndex(index: number, force: boolean = false): Node {
        if (!this._scrollView || !this.datas) {
            return null;
        }
        let children = this._scrollView.content.children;
        for (let i = 0; i < children.length; ++i) {
            if (children[i].getComponent(ScrollItemView).index == index) {
                return children[i];
            }
        }
        if (index > this.datas.length - 1) {
            return null;
        }
        if (force) {
            let itemNode = this._itemPool.get();
            if (!itemNode) {
                itemNode = instantiate(this._itemTemplate) as Node;
                itemNode.active = true;
                this.listener?.onItemAdd(itemNode.getComponent(SuperButton));
            }
            // itemNode["__index"] = index;
            // itemNode["__data"] = this._datas[index];
            itemNode.position = this._getPositionWithIndex(index, _tempVec3);
            this._scrollView.content.addChild(itemNode);

            // //TODO test
            // itemNode.getChildByName("testName")?.destroy();
            // let node = new Node("testName");
            // node.layer = itemNode.layer;
            // let label = node.addComponent(Label);
            // label.string = "" + itemNode["__index"];
            // node.position = v3(0, 0, 0);
            // itemNode.addChild(node);

            // this._scrollView.scheduleOnce(() => {
            //     this._scrollView.content.children.sort((a, b) => a.getComponent(ScrollItemView).index - b.getComponent(ScrollItemView).index);
            // }, 0);
            itemNode.getComponent(ScrollItemView).useFunc(this._datas[index], index);
            return itemNode;
        }
        return null;
    }

    private onScrolling(scrollView: ScrollView) {
        const bounceBackAmount = scrollView["_getHowMuchOutOfBoundary"]();
        // console.log(bounceBackAmount);
        let ignoreUnuse = false;
        //超出边界unuse移除会导致回弹偶尔失效，故ignore unuse
        if (this._scrollView.vertical) {
            if (bounceBackAmount.y != 0) {
                ignoreUnuse = true;
            }
        } else if (this._scrollView.horizontal) {
            if (bounceBackAmount.x != 0) {
                ignoreUnuse = true;
            }
        }
        this._updateRenderItems(ignoreUnuse);
    }

    /**
     * 同步数据添加
     * @param index 
     */
    public syncItemAdd(index: number) {
        let children = this._scrollView.content.children;
        for (let i = 0; i < children.length; ++i) {
            if (children[i].getComponent(ScrollItemView).index >= index) {
                children[i].getComponent(ScrollItemView).index += 1;
                children[i].position = this._getPositionWithIndex(i, _tempVec3);
            }
        }
        this._updateRenderItems();
    }

    /**
     * 同步数据删除
     * @param index 
     */
    public syncItemRemove(index: number) {
        let itemNode = this.getItemWithIndex(index);
        if (itemNode) {
            itemNode.getComponent(SuperButton)?.onUnSelected();
            this._itemPool.put(itemNode);
            itemNode.getComponent(ScrollItemView).unuseFunc();
            this.onItemRemove(itemNode.getComponent(SuperButton));
        }
        let children = this._scrollView.content.children;
        for (let i = 0; i < children.length; ++i) {
            if (children[i].getComponent(ScrollItemView).index > index) {
                children[i].getComponent(ScrollItemView).index -= 1;
                children[i].position = this._getPositionWithIndex(i, _tempVec3);
            }
        }
        this._updateRenderItems();
    }

    /**
     * 同步数据更新
     * @param index 
     */
    public syncItemUpdate(index: number) {
        let itemNode = this.getItemWithIndex(index);
        itemNode.getComponent(ScrollItemView).useFunc(this._datas[index], index);
    }

    /**
     * 移除指定itemNode
     * @param itemNode 
     */
    public removeItem(itemNode: Node) {
        let index = itemNode.getComponent(ScrollItemView).index;
        this.syncItemRemove(index);
    }

    public showItem() {
        //TODO显示item待实现
    }

    public hideItem() {
        //TODO隐藏item待实现
    }

    private onItemRemove(itemNode: SuperButton) {
        if (!itemNode) {
            return;
        }
        if (this._selectedItemView == itemNode) {
            this.selectedItemView = null;
        }
        if (this.defaultSelectedItemView == itemNode) {
            this.defaultSelectedItemView = null;
        }
    }

    public removeAllItems() {
        this.unselectedItemView();
        if (!this._scrollView) {
            return;
        }

        let children = this._scrollView.content.children;
        while (children.length > 0) {
            const itemNode = children[0];
            this._itemPool.put(itemNode);
            itemNode.getComponent(ScrollItemView).unuseFunc();
        }
    }

    public getGridRow(): number {
        return this._gridRow;
    }

    public getRowWithIndex(index: number): number {
        if (this._contentLayout.type == Layout.Type.GRID) {
            return Math.floor(index / this._gridCol);
        } else {
            return index;
        }
    }

    public getPercentOffset(index: number, up: boolean, out: Vec2): Vec2 {
        let itemNode = this.getItemWithIndex(index);
        let row = this.getRowWithIndex(index);
        let percent = row / this._gridRow;
        let scrollOffset = this._scrollView.getScrollOffset();
        if (this._scrollView.vertical) {
            if (up) {
                out.set(0, Math.max(0, this._scrollView.content.getComponent(UITransform).contentSize.height * percent - itemNode.getComponent(UITransform).contentSize.height));
                if (row < this._gridRow - 1) {
                    out.y = Math.min(out.y, scrollOffset.y);
                }
            } else {
                out.set(0, Math.max(0, this._scrollView.content.getComponent(UITransform).contentSize.height * percent - this.node.getComponent(UITransform).contentSize.height + itemNode.getComponent(UITransform).contentSize.height + itemNode.getComponent(UITransform).contentSize.height));
                if (row > 0) {
                    out.y = Math.max(out.y, scrollOffset.y);
                }
            }
        } else if (this._scrollView.horizontal) {
            if (up) {
                out.set(Math.max(0, this._scrollView.content.getComponent(UITransform).contentSize.width * percent - itemNode.getComponent(UITransform).contentSize.width, 0));
                if (row < this._gridRow - 1) {
                    out.x = Math.min(out.x, -scrollOffset.x);
                }
            } else {
                out.set(Math.max(0, this._scrollView.content.getComponent(UITransform).contentSize.width * percent - this.node.getComponent(UITransform).contentSize.width + itemNode.getComponent(UITransform).contentSize.width + itemNode.getComponent(UITransform).contentSize.width, 0));
                if (row > 0) {
                    out.x = Math.max(out.x, -scrollOffset.x);
                }
            }
        }
        return out;
    }

    public getUpIndex(index: number, loop: boolean) {
        if (this._contentLayout.type == Layout.Type.GRID) {
            if (this._contentLayout.startAxis == Layout.AxisDirection.VERTICAL) {
                let row = Math.floor(index / this._gridCol);
                let col = index % this._gridCol;
                if (--col < 0) {
                    col = loop ? this._gridCol - 1 : 0;
                }
                index = Math.min(this.datas.length - 1, row * this._gridCol + col);
            } else if (this._contentLayout.startAxis == Layout.AxisDirection.HORIZONTAL) {
                let row = Math.floor(index / this._gridCol);
                let col = index % this._gridCol;
                if (--row < 0) {
                    row = loop ? this._gridRow - 1 : 0;
                }
                index = Math.min(this.datas.length - 1, row * this._gridCol + col);
            }
        } else {
            if (--index < 0) {
                index = loop ? this.datas.length - 1 : 0;
            }
        }
        return index;
    }

    public getDownIndex(index: number, loop: boolean) {
        if (this._contentLayout.type == Layout.Type.GRID) {
            if (this._contentLayout.startAxis == Layout.AxisDirection.VERTICAL) {
                let row = Math.floor(index / this._gridCol);
                let col = index % this._gridCol;
                if (++col > this._gridCol - 1) {
                    col = loop ? 0 : this._gridCol - 1;
                }
                index = Math.min(this.datas.length - 1, row * this._gridCol + col);
            } else if (this._contentLayout.startAxis == Layout.AxisDirection.HORIZONTAL) {
                let row = Math.floor(index / this._gridCol);
                let col = index % this._gridCol;
                if (++row > this._gridRow - 1) {
                    row = loop ? 0 : this._gridRow - 1;
                }
                index = Math.min(this.datas.length - 1, row * this._gridCol + col);
            }
        } else {
            if (++index > this.datas.length - 1) {
                index = loop ? 0 : this.datas.length - 1;
            }
        }
        return index;
    }

    public getLeftIndex(index: number, loop: boolean) {
        if (this._contentLayout.type == Layout.Type.GRID) {
            if (this._contentLayout.startAxis == Layout.AxisDirection.VERTICAL) {
                let row = Math.floor(index / this._gridCol);
                let col = index % this._gridCol;
                if (--row < 0) {
                    row = loop ? this._gridRow - 1 : 0;
                }
                index = Math.min(this.datas.length - 1, row * this._gridCol + col);
            } else if (this._contentLayout.startAxis == Layout.AxisDirection.HORIZONTAL) {
                let row = Math.floor(index / this._gridCol);
                let col = index % this._gridCol;
                if (--col < 0) {
                    col = loop ? this._gridCol - 1 : 0;
                }
                index = Math.min(this.datas.length - 1, row * this._gridCol + col);
            }
        } else {
            if (--index < 0) {
                index = loop ? this.datas.length - 1 : 0;
            }
        }
        return index;
    }

    public getRightIndex(index: number, loop: boolean) {
        if (this._contentLayout.type == Layout.Type.GRID) {
            if (this._contentLayout.startAxis == Layout.AxisDirection.VERTICAL) {
                let row = Math.floor(index / this._gridCol);
                let col = index % this._gridCol;
                if (++row > this._gridRow - 1) {
                    row = loop ? 0 : this._gridRow - 1;
                }
                index = Math.min(this.datas.length - 1, row * this._gridCol + col);
            } else if (this._contentLayout.startAxis == Layout.AxisDirection.HORIZONTAL) {
                let row = Math.floor(index / this._gridCol);
                let col = index % this._gridCol;
                if (++col > this._gridCol - 1) {
                    col = loop ? 0 : this._gridCol - 1;
                }
                index = Math.min(this.datas.length - 1, row * this._gridCol + col);
            }
        } else {
            if (++index > this.datas.length - 1) {
                index = loop ? 0 : this.datas.length - 1;
            }
        }
        return index;
    }

    /**
     * 选中第一项
     * @returns 
     */
    public selectedDefaultItem() {
        if (this.defaultSelectedItemView) {
            if (this.selectedItemView) {
                this.selectedItemView.onFocusEvent()
            } else {
                // let itemView = this.getItemWithIndex(0)?.getComponent(SuperButton);
                // if (itemView) {
                //     itemView.onClickForContainer();
                // }
                this.defaultSelectedItemView.onClickForContainer();
            }
        }
    }
    findDefaultItem() {
        if (!this.defaultSelectedItemView) {
            let df = null;
            let count = this.content.children.length;
            for (let index = 0; index < count; index++) {
                const element = this.content.children[index];
                if (element.active) {
                    df = element.getComponent(SuperButton);
                    if (df) {
                        break;
                    }
                }
            }
            if (df) {
                this.defaultSelectedItemView = df
            } else {
                console.log('没有可以作为默认选项的item')
            }
        }
    }

    /**
     * 主轴方向移动到上一个
     * @returns 
     */
    public moveUp() {
        if (!this._verticalMoveable) {
            return false;
        }
        if (!this._selectedItemView) {
            this.findDefaultItem()
            this.selectedDefaultItem();
        }
        if (!this._selectedItemView) {
            return false;
        }
        let lastIndex = this._selectedItemView.getComponent(ScrollItemView).index;
        let index = this.getUpIndex(lastIndex, this.loop);
        if (index == lastIndex) {
            return false;
        }
        let targetCursorItemNode = this.getItemWithIndex(index, true);
        targetCursorItemNode.getComponent(SuperButton).onClickForContainer();
        this.getPercentOffset(index, true, _tempVec2);
        this.scrollView.scrollToOffset(_tempVec2, 0.2);
        return true;
    }

    /**
     * 主轴方向移动到下一个
     * @returns 
     */
    public moveDown() {
        if (!this._verticalMoveable) {
            return false;
        }
        if (!this._selectedItemView) {
            this.findDefaultItem()
            this.selectedDefaultItem();
        }
        if (!this._selectedItemView) {
            return false;
        }
        let lastIndex = this._selectedItemView.getComponent(ScrollItemView).index;
        let index = this.getDownIndex(lastIndex, this.loop);
        if (index == lastIndex) {
            return false;
        }
        let targetCursorItemNode = this.getItemWithIndex(index, true);
        targetCursorItemNode.getComponent(SuperButton).onClickForContainer();
        this.getPercentOffset(index, false, _tempVec2);
        this.scrollView.scrollToOffset(_tempVec2, 0.2);
        return true;
    }

    /**
     * 交叉轴方向移动到上一个
     * @returns 
     */
    public moveLeft() {
        if (!this._horizontalMoveable) {
            return false;
        }
        if (!this._selectedItemView) {
            this.findDefaultItem()
            this.selectedDefaultItem();
        }
        if (!this._selectedItemView) {
            return false;
        }
        let lastIndex = this._selectedItemView.getComponent(ScrollItemView).index;
        let index = this.getLeftIndex(lastIndex, this.loop);
        if (index == lastIndex) {
            return false;
        }
        let targetCursorItemNode = this.getItemWithIndex(index, true);
        targetCursorItemNode.getComponent(SuperButton).onClickForContainer();
        this.getPercentOffset(index, true, _tempVec2);
        this.scrollView.scrollToOffset(_tempVec2, 0.2);
        return true;
    }

    /**
     * 交叉轴方向移动到下一个
     * @returns 
     */
    public moveRight() {
        if (!this._horizontalMoveable) {
            return false;
        }
        if (!this._selectedItemView) {
            this.findDefaultItem()
            this.selectedDefaultItem();
        }
        if (!this._selectedItemView) {
            return false;
        }
        let lastIndex = this._selectedItemView.getComponent(ScrollItemView).index;
        let index = this.getRightIndex(lastIndex, this.loop);
        if (index == lastIndex) {
            return false;
        }
        let targetCursorItemNode = this.getItemWithIndex(index, true);
        targetCursorItemNode.getComponent(SuperButton).onClickForContainer();
        this.getPercentOffset(index, false, _tempVec2);
        this.scrollView.scrollToOffset(_tempVec2, 0.2);
        return true;
    }

    initItems() {
        for (let i = 0; i < this._datas.length; ++i) {
            this._useItem(i);
        }
    }
}

/**
 * [1] Class member could be defined like this.
 * [2] Use `property` decorator if your want the member to be serializable.
 * [3] Your initialization goes here.
 * [4] Your update function goes here.
 *
 * Learn more about scripting: https://docs.cocos.com/creator/3.3/manual/zh/scripting/
 * Learn more about CCClass: https://docs.cocos.com/creator/3.3/manual/zh/scripting/ccclass.html
 * Learn more about life-cycle callbacks: https://docs.cocos.com/creator/3.3/manual/zh/scripting/life-cycle-callbacks.html
 */
